package com.ajk.server.service.impl;
import java.util.Collections;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ajk.server.controller.events.CreditsEvent;
import com.ajk.server.dao.CreditsHistoryMapper;
import com.ajk.server.exception.AjkException;
import com.ajk.server.exception.ErrorConstant;
import com.ajk.server.model.CreditsCategory;
import com.ajk.server.model.CreditsHistory;
import com.ajk.server.model.query.CreditsHistoryQuery;
import com.ajk.server.service.CreditsHistoryService;
import com.ajk.server.utils.IntegerUtil;
import com.ajk.server.utils.RedisKeyUtil;
import com.ajk.server.utils.SpringContextUtil;

/**
 * 积分历史  <br>
 * t_credits_history <br>
 * v1.0 2016-05-01
 */
@Service
public class CreditsHistoryServiceImpl implements CreditsHistoryService {

	private static final Logger logger = LoggerFactory.getLogger(CreditsHistoryServiceImpl.class);

	@Autowired
	private CreditsHistoryMapper creditsHistoryMapper;

	@Autowired
	private RedisTemplate<String,Object> template;

	/**
	 *根据ID删除 积分历史
	 */
	@Override
	public Integer deleteCreditsHistoryById(Integer id){
		return creditsHistoryMapper.deleteById(id);
	}

	/**
	 *新增 积分历史
	 */
	@Override
	@Transactional
	public Integer batchInsertCreditsHistory(List<? extends CreditsHistory> creditsHistorys){
		Integer count = creditsHistoryMapper.batchInsert(creditsHistorys);
		return count;
	}
	/**
	 *新增 积分历史
	 */
	@Override
	@Transactional
	public Integer insertCreditsHistory(CreditsHistory domain){
		int categoryId = domain.getCategoryId();
		CreditsCategory creditsCategory = CreditsCategory.findCreditsCategoryByValue(categoryId);
		Integer userId = domain.getUserId();
		Integer id = null;
		if(creditsCategory!=null){
			if(creditsCategory == CreditsCategory.SIGN_IN){
				//判断当天是否已经签到
				String key = RedisKeyUtil.userSignInValueKey(userId);

				if(!template.hasKey(key)){
					template.opsForValue().set(key, true);
					String expireDateStr = DateTime.now().plusDays(1).toString("yyyy-MM-dd");
					DateTime expireDate = new DateTime(expireDateStr);
					expireDate = expireDate.plusMinutes(1);
					template.expireAt(key, expireDate.toDate());
				}
			}
			id = creditsHistoryMapper.insert(domain);
			if(IntegerUtil.isPositiveInteger(id)){
				//计算总积分数
				String key = RedisKeyUtil.userCreditTotalValueKey(userId);
				Integer num = creditsCategory.getNum();
				if(template.hasKey(key)){
					Object total = template.opsForValue().get(key);
					if(total instanceof Integer){
						total = (Integer) total + num;
						template.opsForValue().set(key, total);
//						template.expire(key, 7, TimeUnit.DAYS);
					}
				}else{
					//数据库加载
					Integer count = creditsHistoryMapper.getTotalCredit(userId);
					if(count==null){
						count = 0;
					}
					template.opsForValue().set(key, count);
//					template.expire(key, 7, TimeUnit.DAYS);
				}
			}
		}
		return id;
	}

	/**
	 *更新 积分历史
	 */
	@Override
	@Transactional
	public Integer updateCreditsHistory(CreditsHistory domain){
		Integer count = creditsHistoryMapper.update(domain);
		return count;
	}

	/**
	 *根据ID查询 积分历史
	 */
	public CreditsHistory findCreditsHistoryById(Integer id){
		CreditsHistory result = creditsHistoryMapper.findById(id);
		if(result!=null){
			result.dealWith();
		}
		return result;
	}

	/**
	 *通过query 查询 积分历史
	 */
	public List<CreditsHistory> findCreditsHistoryByQuery(CreditsHistoryQuery query){
		query.dealWith();
		List<CreditsHistory> result = creditsHistoryMapper.findByQuery(query);
		if(CollectionUtils.isNotEmpty(result)) {
			Collections.sort(result);
			for (CreditsHistory creditsHistory : result) {
				creditsHistory.dealWith();
			}
		}
		return result;
	}	

	/**
	 *通过query count总条数
	 */
	public Integer countCreditsHistoryByQuery(CreditsHistoryQuery query){
		query.dealWith();
		Integer result = creditsHistoryMapper.countByQuery(query);
		return result;
	}

	/**
	 * 通过ids查询
	 */
	public List<CreditsHistory> findCreditsHistoryByIds(List<Integer> ids){
		List<CreditsHistory> result = creditsHistoryMapper.findByIds(ids);
		if(CollectionUtils.isNotEmpty(result)) {
			for (CreditsHistory creditsHistory : result) {
				creditsHistory.dealWith();
			}
		}
		return result;
	}

	@Override
	public Integer signIn(Integer userId) {
		
		if(todayIsSign(userId)){
			AjkException exception = new AjkException(ErrorConstant.PARAM_ERROR.getErrorCode(), "您今天已经签到了");
			logger.error("签到失败",exception);
			throw exception;
		}
		
		SpringContextUtil.getApplicationContext().publishEvent(new CreditsEvent(userId, userId, CreditsCategory.SIGN_IN));
		
		return CreditsCategory.SIGN_IN.getNum();
	}

	@Override
	public boolean todayIsSign(Integer userId) {
		String key = RedisKeyUtil.userSignInValueKey(userId);
		if(template.hasKey(key)){
			return true;
		}else{
			CreditsHistory cHistory = creditsHistoryMapper.findTodaySingin(userId);
			if(cHistory!=null){
				template.opsForValue().set(key, true);
				String expireDateStr = DateTime.now().plusDays(1).toString("yyyy-MM-dd");
				DateTime expireDate = new DateTime(expireDateStr);
				expireDate.plusMinutes(1);
				template.expireAt(key, expireDate.toDate());
				return true;
			}
		}
		return false;
	}

	@Override
	public Integer findMyCreditsAmount(Integer userId) {
		Integer count = 0;
		if(IntegerUtil.isPositiveInteger(userId)){
			//计算总积分数
			String key = RedisKeyUtil.userCreditTotalValueKey(userId);
			if(template.hasKey(key)){
				Object object = template.opsForValue().get(key);
				if(object instanceof Integer){
					count = (Integer) object;
				}
			}else{
				//数据库加载
				count = creditsHistoryMapper.getTotalCredit(userId);
				if(count==null){
					count = 0;
				}
				template.opsForValue().set(key, count);
//				template.expire(key, 7, TimeUnit.DAYS);
			}
		}
		return count;
	}

}	